package com.nyway.wehos2r.client.content.music;

import java.util.Comparator;

import com.google.gwt.cell.client.TextCell;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.RunAsyncCallback;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.i18n.client.Constants;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler;
import com.google.gwt.user.cellview.client.SimplePager;
import com.google.gwt.user.cellview.client.SimplePager.TextLocation;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.gwt.view.client.SelectionModel;
import com.google.gwt.view.client.SingleSelectionModel;
import com.nyway.wehos2r.client.ContentWidget;
import com.nyway.wehos2r.client.WeHostOurContext;
import com.nyway.wehos2r.client.content.music.SongDatabase.SongInfo;
import com.nyway.wehos2r.client.content.music.event.PlaySongEvent;

public class SongTable extends ContentWidget {

	/**
	 * The UiBinder interface used by this example.
	 */
	interface Binder extends UiBinder<Widget, SongTable> {
	}

	/**
	 * The constants used in this Content Widget.
	 */
	public static interface CwConstants extends Constants {
		String songTableName();

		String songTableTime();

		String songTableAlbum();

		String songTableArtist();

		String songTableRating();

		String songTableCategory();
	}

	/**
	 * The main CellTable.
	 */
	@UiField(provided = true)
	CellTable<SongInfo> cellTable;

	/**
	 * The pager used to change the range of data.
	 */
	@UiField(provided = true)
	SimplePager pager;

	/**
	 * An instance of the constants.
	 */
	private final CwConstants constants;

	/**
	 * Constructor.
	 * 
	 * @param constants
	 *            the constants
	 */
	public SongTable(CwConstants constants) {
		super("songs", "", false);
		this.constants = constants;
	}

	@Override
	public boolean hasMargins() {
		return false;
	}

	/**
	 * Initialize this example.
	 */
	@Override
	public Widget onInitialize() {
		// Create a CellTable.

		// Set a key provider that provides a unique key for each contact. If
		// key is
		// used to identify contacts when fields (such as the name and address)
		// change.
		cellTable = new CellTable<SongInfo>(SongDatabase.SongInfo.KEY_PROVIDER);
		cellTable.setWidth("100%", true);

		// Attach a column sort handler to the ListDataProvider to sort the
		// list.
		ListHandler<SongInfo> sortHandler = new ListHandler<SongInfo>(
				SongDatabase.get().getDataProvider().getList());
		cellTable.addColumnSortHandler(sortHandler);

		// Create a Pager to control the table.
		SimplePager.Resources pagerResources = GWT
				.create(SimplePager.Resources.class);
		pager = new SimplePager(TextLocation.CENTER, pagerResources, false, 0,
				true);
		pager.setDisplay(cellTable);

		final SingleSelectionModel<SongInfo> selectionModel = new SingleSelectionModel<SongInfo>(
				SongDatabase.SongInfo.KEY_PROVIDER);
		// DefaultSelectionEventManager<SongInfo> selectionEventManager =
		// DefaultSelectionEventManager
		// .createCheckboxManager();
		// cellTable.setSelectionModel(selectionModel, selectionEventManager);
		cellTable.setSelectionModel(selectionModel);
		selectionModel
				.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
					@Override
					public void onSelectionChange(SelectionChangeEvent event) {
						WeHostOurContext.EVENT_BUS
								.fireEvent(new PlaySongEvent(selectionModel
										.getSelectedObject()));
					}
				});

		initTableColumns(selectionModel, sortHandler);

		// Add the CellList to the adapter in the database.
		SongDatabase.get().addDataDisplay(cellTable);

		// Create the UiBinder.
		Binder uiBinder = GWT.create(Binder.class);
		Widget widget = uiBinder.createAndBindUi(this);

		return widget;
	}

	@Override
	protected void asyncOnInitialize(final AsyncCallback<Widget> callback) {
		GWT.runAsync(SongTable.class, new RunAsyncCallback() {

			@Override
			public void onFailure(Throwable caught) {
				callback.onFailure(caught);
			}

			@Override
			public void onSuccess() {
				callback.onSuccess(onInitialize());
			}
		});
	}

	/**
	 * Add the columns to the table.
	 */
	private void initTableColumns(
			final SelectionModel<SongInfo> selectionModel,
			ListHandler<SongInfo> sortHandler) {
		// Name.
		Column<SongInfo, String> nameColumn = new Column<SongInfo, String>(
				new TextCell()) {
			@Override
			public String getValue(SongInfo object) {
				return object.getName();
			}

		};
		nameColumn.setSortable(true);
		sortHandler.setComparator(nameColumn, new Comparator<SongInfo>() {
			@Override
			public int compare(SongInfo o1, SongInfo o2) {
				return o1.getName().compareTo(o2.getName());
			}
		});
		cellTable.addColumn(nameColumn, constants.songTableName());
		cellTable.setColumnWidth(nameColumn, 20, Unit.PCT);

		// Artist.
		Column<SongInfo, String> artistColumn = new Column<SongInfo, String>(
				new TextCell()) {
			@Override
			public String getValue(SongInfo object) {
				return object.getArtist();
			}
		};
		artistColumn.setSortable(true);
		sortHandler.setComparator(artistColumn, new Comparator<SongInfo>() {
			@Override
			public int compare(SongInfo o1, SongInfo o2) {
				return o1.getArtist().compareTo(o2.getArtist());
			}
		});
		cellTable.addColumn(artistColumn, constants.songTableArtist());
		cellTable.setColumnWidth(artistColumn, 20, Unit.PCT);

		// Category.
		Column<SongInfo, String> categoryColumn = new Column<SongInfo, String>(
				new TextCell()) {
			@Override
			public String getValue(SongInfo object) {
				return object.getCategory().getDisplayName();
			}
		};
		cellTable.addColumn(categoryColumn, constants.songTableCategory());
		cellTable.setColumnWidth(categoryColumn, 130, Unit.PX);

		// Albums
		Column<SongInfo, String> albumColumn = new Column<SongInfo, String>(
				new TextCell()) {
			@Override
			public String getValue(SongInfo object) {
				return object.getAlbum();
			}
		};
		albumColumn.setSortable(true);
		sortHandler.setComparator(albumColumn, new Comparator<SongInfo>() {
			@Override
			public int compare(SongInfo o1, SongInfo o2) {
				return o1.getAlbum().compareTo(o2.getAlbum());
			}
		});
		cellTable.addColumn(albumColumn, constants.songTableAlbum());
		cellTable.setColumnWidth(albumColumn, 60, Unit.PCT);
	}
}
